/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.file.web;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.utils.FTPUtils;
import com.thinkgem.jeesite.common.utils.Msg;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.file.entity.FTPBean;
import com.thinkgem.jeesite.modules.file.entity.TpFileuploadInfo;
import com.thinkgem.jeesite.modules.file.service.TpFileuploadInfoService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 文件上传Controller
 *
 * @author 康力
 * @version 2018-03-07
 */
@Controller
@RequestMapping(value = "${adminPath}/file/tpFileuploadInfo")
public class TpFileuploadInfoController extends BaseController {

    @Autowired
    private TpFileuploadInfoService tpFileuploadInfoService;
    @Autowired
    private FTPBean ftpBean;

    @ModelAttribute
    public TpFileuploadInfo get(@RequestParam(required = false) String id) {
        TpFileuploadInfo entity = null;
        if (StringUtils.isNotBlank(id)) {
            entity = tpFileuploadInfoService.get(id);
        }
        if (entity == null) {
            entity = new TpFileuploadInfo();
        }
        return entity;
    }

    @RequiresPermissions("file:tpFileuploadInfo:view")
    @RequestMapping(value = {"list", ""})
    public String list(TpFileuploadInfo tpFileuploadInfo, HttpServletRequest request, HttpServletResponse response, Model model) {
        Page<TpFileuploadInfo> page = tpFileuploadInfoService.findPage(new Page<TpFileuploadInfo>(request, response), tpFileuploadInfo);
        model.addAttribute("page", page);
        model.addAttribute("model", request.getParameter("model"));
        model.addAttribute("fileType", request.getParameter("fileType"));
        return "modules/file/tpFileuploadInfoList";
    }
    /**
     * 根据条件获得文件数据列表 
     * @param tpFileuploadInfo
     * @param request
     * @param response
     * @param model
     * @return
     */
    @RequestMapping("getFileList")
    @ResponseBody
    public Object getFileList(TpFileuploadInfo tpFileuploadInfo, HttpServletRequest request, HttpServletResponse response, Model model){
    	List<TpFileuploadInfo> fileList = tpFileuploadInfoService.findList(tpFileuploadInfo);
    	return fileList;
    }
    @RequiresPermissions("file:tpFileuploadInfo:view")
    @RequestMapping(value = "form")
    public String form(TpFileuploadInfo tpFileuploadInfo, Model m) {
        m.addAttribute("tpFileuploadInfo", tpFileuploadInfo);
        m.addAttribute("model", tpFileuploadInfo.getModel());
        m.addAttribute("fileType", tpFileuploadInfo.getFileType());
        return "modules/file/tpFileuploadInfoForm";
    }

    @RequiresPermissions("file:tpFileuploadInfo:edit")
    @RequestMapping(value = "save")
    public String save(TpFileuploadInfo tpFileuploadInfo, Model model, RedirectAttributes redirectAttributes, String files) {
        /*if (!beanValidator(model, tpFileuploadInfo)) {
            return form(tpFileuploadInfo, model);
        }*/
        if (tpFileuploadInfo.getIsNewRecord()) {
            if (files != null) {
                files = files.replace("&quot;", "\"");
                ObjectMapper mapper = new ObjectMapper();
                JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, TpFileuploadInfo.class);
                try {
                    List<TpFileuploadInfo> list = (List<TpFileuploadInfo>) mapper.readValue(files, javaType);
                    Msg msg = upload(list, tpFileuploadInfo);
                    addMessage(redirectAttributes, msg.getCode() == Msg.FAIL ? "保存文件失败" : "保存文件成功");
                    System.out.println("files>>>>>> " + list);
                } catch (IOException e) {
                    e.printStackTrace();
                    addMessage(redirectAttributes, "保存文件失败");
                }
            }
        } else {
            tpFileuploadInfoService.save(tpFileuploadInfo);
            addMessage(redirectAttributes, "保存文件成功");
        }
        return "redirect:" + Global.getAdminPath() + "/file/tpFileuploadInfo/list?model="+tpFileuploadInfo.getModel();
    }

    @RequiresPermissions("file:tpFileuploadInfo:edit")
    @RequestMapping(value = "delete")
    public String delete(TpFileuploadInfo tpFileuploadInfo, RedirectAttributes redirectAttributes) {
        tpFileuploadInfoService.delete(tpFileuploadInfo);
        addMessage(redirectAttributes, "删除文件成功");
        return "redirect:" + Global.getAdminPath() + "/file/tpFileuploadInfo/?repage";
    }

    //====================文件上传=================

    /**
     * 文件下载
     *
     * @param response
     * @param id
     */
    @RequestMapping("/download")
    public void showFile(HttpServletResponse response, String id) {
        try {
            TpFileuploadInfo file = tpFileuploadInfoService.get(id);
//            ftpBean.setStorePath("/home/ftp"+ftpBean.getRootPath());
            ftpBean.setFtpFileName(file.getFilePath());
            ftpBean.setOriginalFileName(file.getFileName());
            boolean downFile = FTPUtils.downFile(ftpBean, response);
            if (!downFile) {
                logger.debug("下载文件失败！");
                throw new Exception("文件下载失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.debug("下载文件成功！");
    }

    /**
     * 文件上传记录到数据库
     *
     * @param files
     * @param fileuploadInfo
     * @return
     */
  /*  @ResponseBody
    @RequestMapping("/upload")*/
    private Msg upload(List<TpFileuploadInfo> files, TpFileuploadInfo fileuploadInfo) {
        //User user = UserUtils.getUser();
        if (org.apache.commons.lang3.StringUtils.trimToNull(fileuploadInfo.getRemarks()) != null) {
            for (TpFileuploadInfo file : files) {
                file.setFileType(fileuploadInfo.getFileType());
                file.setModel(fileuploadInfo.getModel());
                file.setRemarks(fileuploadInfo.getRemarks());
                file.setIsNewRecord(false);
            }
        } else {
            for (TpFileuploadInfo file : files) {
                file.setFileType(fileuploadInfo.getFileType());
                file.setModel(fileuploadInfo.getModel());
                file.setIsNewRecord(false);
            }
        }
        return tpFileuploadInfoService.batchInsert(files);
    }


    /**
     * 多文件上传，为解决上传经常失败问题，使用同步方法
     *
     * @param file
     * @return
     * @throws InterruptedException
     */
    @ResponseBody
    @RequestMapping("/preUpload")
    public synchronized Object preUpload(@RequestParam("file") MultipartFile file) throws InterruptedException {
        Map<String, Object> m = new HashMap<String, Object>();
        try {
//            ftpBean.setStorePath("/home/ftp"+ftpBean.getRootPath());
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            String ftpName = new StringBuilder().append(UUID.randomUUID().toString().replaceAll("-", "")).append(".").append(extension).toString();
            ftpBean.setFtpFileName(ftpName);
            logger.debug("准备上传文件： " + file.getOriginalFilename());
            boolean b = uploadFile(ftpBean, file.getInputStream());
            logger.debug(b ? "上传文件成功 " : "上传文件失败");
            TpFileuploadInfo uploadFile = new TpFileuploadInfo();
            uploadFile.setFileName(file.getOriginalFilename());
            uploadFile.setSize(file.getSize());
            uploadFile.setFilePath(ftpName);
            uploadFile.setSuffix(extension != null ? extension.toLowerCase() : extension);
            m.put("file", uploadFile);
            m.put("code", b ? 0 : 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return m;
    }

    @RequestMapping("/reviewImg/{id}")
    public void showImg(@PathVariable("id") String id, HttpServletResponse response) {
        try {
            TpFileuploadInfo uploadFile = get(id);
            ftpBean.setOriginalFileName(uploadFile.getFileName());
             ftpBean.setFtpFileName(uploadFile.getFilePath());
//            ftpBean.setStorePath("/home/ftp"+ftpBean.getRootPath());
            FTPUtils.FileShowInPage(ftpBean, response, "image/*", null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public synchronized boolean uploadFile(FTPBean bean, InputStream in) {
        boolean success = false;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(bean.getHost(), bean.getPort());// 连接FTP服务器
            // 如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务器
            boolean login = ftp.login(bean.getLoginName(), bean.getPassword());// 登录
            if (!login) {
                logger.debug("----->>>ftp服务器认证失败！");
                return success;
            }
            // 设置以二进制方式传输
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                logger.debug("----------->>>连接ftp服务器失败");
                return success;
            }
            if (!ftp.changeWorkingDirectory(bean.getStorePath())) {
                if (!CreateDirecroty(ftp, bean.getStorePath())) {
                    logger.info("----->>>创建目录失败……");
                    return success;
                }
            }
            ftp.enterLocalPassiveMode();
            boolean storeFile = ftp.storeFile(bean.getFtpFileName(), in);
            System.out.println(storeFile);
            if (!storeFile) {
                logger.debug("----->>>上传文件失败！");
                return success;
            }
            in.close();
            ftp.logout();
            success = true;
        } catch (IOException e) {
            logger.error("----->>>异常" + e.getMessage());
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return success;
    }

    public synchronized boolean CreateDirecroty(FTPClient ftp, String path) throws IOException {
        boolean success = true;
        String directory = path.substring(0, path.lastIndexOf("/") + 1);
        logger.debug(directory);
        // 如果远程目录不存在，则循环创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !ftp.changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            start = (directory.startsWith("/")) ? 1 : 0;
            end = directory.indexOf("/", start);
            while (true) {
                String subDirectory = new String(path.substring(start, end));
                if (!ftp.changeWorkingDirectory(subDirectory)) {
                    logger.debug(">>>准备创建的目录： " + subDirectory);
                    if (ftp.makeDirectory(subDirectory)) {
                        ftp.changeWorkingDirectory(subDirectory);
                        logger.debug(">>>创建目录成功： " + subDirectory);
                    } else {
                        logger.debug("创建目录失败");
                        success = false;
                        return success;
                    }
                }
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }
}